/*
 * wh2_syscalls.c
 *
 *  Created on: 24/04/2012
 *      Author: Roy
 */


#include <linux/sched.h>
#include <asm/uaccess.h> // copy_from_user


#define MODE_REGULAR 301
#define MODE_RANDOM 302

extern int random; // init: 0
extern struct random_params params_p;
extern struct switch_info info[150];
extern int counter; // init 0;
extern int cur_index; // init 0
extern int is_full;

int sys_sched_setmachnism(int mode, struct random_params* params){
	int temp=random;
	if(mode==MODE_RANDOM){
		if(params==NULL || params->p_prio<1 || params->p_prio>100 || params->p_epoch<1 ||
			params->p_epoch>100 || params->p_interactive<1 || params->p_interactive>100){
			return -EINVAL;
			}
		if(temp!=1){
			counter=0;
		}
		random=1;
		if(copy_from_user(&params_p, params, sizeof(struct random_params))!=0){
				return -ENOSPC;
		}
		return (temp==1)? MODE_RANDOM: MODE_REGULAR;
	}

if(mode==MODE_REGULAR){
	if(params!=NULL) return -EINVAL;
	if(temp!=0) counter=0;
	random=0;
	return (temp==1)? MODE_RANDOM: MODE_REGULAR;
	}
	return -EINVAL;
}

int sys_sched_getmechanism(struct random_params* params){
	if(params==NULL) return -EINVAL;
	if(!random){
		return MODE_REGULAR;
	}
	if( copy_to_user(params,&params_p, sizeof(struct random_params))!=0){
		return -ENOSPC;
	}
	return MODE_RANDOM;
}

int sys_is_interactive(int pid){
	task_t* p;
	if(pid==0) p=current;
	else p=find_task_by_pid(pid);
	if(p==NULL){
		return -EINVAL;
	}
	return  get_interactive(p);
}

int sys_get_cur_running_priority(int* best_ready_priority){
	int temp;
	if(best_ready_priority==NULL){
		return -EINVAL;
	}
	temp=get_cur_priority();
	if(copy_to_user(best_ready_priority, &temp, sizeof(int))!=0){
		return -ENOSPC;
	}
	return current->prio;
}

int sys_get_scheduling_statistics(struct switch_info* result){
	if(result==NULL){
		return -EINVAL;
	}
	if(is_full==1){
		if(copy_to_user(result, info + cur_index,
					(150 - cur_index)*sizeof(struct switch_info))!=0){
			return -ENOSPC;
		}
		if(copy_to_user(result + (150 - cur_index), info, cur_index*sizeof(struct switch_info))!=0){
			return -ENOSPC;
		}
		return 150;
		}
	else{
		if(copy_to_user(result, info, sizeof(struct switch_info)*cur_index)!=0){
			return -ENOSPC;
		}
		return cur_index;
	}
}
